<!-- AI Chat View -->
<script setup lang="ts">
import { ref, onMounted, nextTick, watch, computed, onBeforeUnmount } from 'vue'
import { useAIStore, type ChatMessage } from '../stores/ai'
import { message } from '@tauri-apps/plugin-dialog'
import MessageEditDialog from '../components/MessageEditDialog.vue'
import { writeText } from '@tauri-apps/plugin-clipboard-manager'
import { useWindowSize } from '@vueuse/core'
import { useDebounceFn } from '@vueuse/core'
import { marked } from 'marked'

// 配置 marked
marked.setOptions({
  gfm: true, // 启用 GitHub 风格的 markdown
  breaks: true, // 启用换行符
  pedantic: false,
  silent: false
})

const aiStore = useAIStore()
const messageInput = ref('')
const chatContainer = ref<HTMLElement | null>(null)
const showSettings = ref(false)
const isSidebarCollapsed = ref(false)
const showApiKey = ref(false)
const showModelDropdown = ref(false)
const sidebarWidth = computed(() => isSidebarCollapsed.value ? 56 : 256)

// 消息折叠状态管理
const collapsedMessages = ref<Set<number>>(new Set())
const MESSAGE_COLLAPSE_THRESHOLD = 300 // 超过300字符的消息会被折叠

// 检查消息是否应该被折叠
const shouldCollapseMessage = (content: string) => {
  return content.length > MESSAGE_COLLAPSE_THRESHOLD
}

// 切换消息折叠状态
const toggleMessageCollapse = (timestamp: number) => {
  const newCollapsedMessages = new Set(collapsedMessages.value)
  if (newCollapsedMessages.has(timestamp)) {
    newCollapsedMessages.delete(timestamp)
  } else {
    newCollapsedMessages.add(timestamp)
  }
  collapsedMessages.value = newCollapsedMessages
}

// 获取消息预览内容
const getPreviewContent = (content: string) => {
  const lastSpaceIndex = content.slice(0, MESSAGE_COLLAPSE_THRESHOLD).lastIndexOf(' ')
  const cutoffIndex = lastSpaceIndex > MESSAGE_COLLAPSE_THRESHOLD * 0.8 ? lastSpaceIndex : MESSAGE_COLLAPSE_THRESHOLD
  return content.slice(0, cutoffIndex) + '...'
}

// 检查消息是否已折叠
const isMessageCollapsed = (timestamp: number) => {
  return collapsedMessages.value.has(timestamp)
}

// 获取消息显示内容
const getMessageContent = (msg: ChatMessage) => {
  if (shouldCollapseMessage(msg.content) && isMessageCollapsed(msg.timestamp)) {
    return getPreviewContent(msg.content)
  }
  return msg.content
}

const scrollToBottom = async () => {
  await nextTick()
  if (chatContainer.value) {
    chatContainer.value.scrollTo({
      top: chatContainer.value.scrollHeight,
      behavior: 'smooth'
    })
  }
}

// 优化侧边栏响应式处理
const { width: windowWidth } = useWindowSize()
const autoHandleSidebar = () => {
  isSidebarCollapsed.value = windowWidth.value < 768
}

// 消息输入防抖
const debouncedScrollToBottom = useDebounceFn(scrollToBottom, 100)

// 添加输入框自动调整高度
const textareaRef = ref<HTMLTextAreaElement | null>(null)
const adjustTextareaHeight = () => {
  if (textareaRef.value) {
    textareaRef.value.style.height = 'auto'
    textareaRef.value.style.height = `${Math.min(textareaRef.value.scrollHeight, 200)}px`
  }
}

// 监听窗口大小变化
watch(windowWidth, autoHandleSidebar)

// 监听消息输入变化
watch(messageInput, () => {
  adjustTextareaHeight()
  debouncedScrollToBottom()
})

// 监听会话变化
watch(() => aiStore.currentSessionId, () => {
  const newCollapsedMessages = new Set<number>()
  const currentSession = aiStore.getCurrentSession()
  if (currentSession) {
    currentSession.messages.forEach(msg => {
      if (shouldCollapseMessage(msg.content)) {
        newCollapsedMessages.add(msg.timestamp)
      }
    })
  }
  collapsedMessages.value = newCollapsedMessages
  nextTick(() => {
    scrollToBottom()
    // 自动聚焦输入框
    textareaRef.value?.focus()
  })
})

// 监听消息变化
watch(
  () => aiStore.getCurrentSession()?.messages,
  () => {
    nextTick(() => {
      scrollToBottom()
    })
  },
  { deep: true }
)

onMounted(() => {
  autoHandleSidebar()
  if (!aiStore.currentSessionId) {
    aiStore.createSession()
  }
  nextTick(() => {
    scrollToBottom()
    // 自动聚焦输入框
    textareaRef.value?.focus()
  })
  document.addEventListener('click', handleClickOutside)
})

onBeforeUnmount(() => {
  document.removeEventListener('click', handleClickOutside)
})

// 添加终止状态管理
const isMessageTerminated = ref(false)

// 修改发送消息函数
const sendMessage = async () => {
  if (!messageInput.value.trim() || aiStore.isProcessing) return
  
  const currentConfig = aiStore.getCurrentModelConfig()
  if (!currentConfig?.apiKey) {
    await message('请先在设置中配置API密钥', { title: '提示' })
    showSettings.value = true
    return
  }
  const userInput = messageInput.value
  messageInput.value = ''
  isMessageTerminated.value = false
  
  // 如果没有当前会话，创建一个新的
  let currentSession = aiStore.getCurrentSession()
  if (!currentSession) {
    currentSession = aiStore.createSession()
  }
  
  // 如果是新会话，且有system prompt，则先添加system消息
  if (currentSession.messages.length === 0 && currentConfig.systemPrompt) {
    aiStore.addMessage({
      role: 'system',
      content: currentConfig.systemPrompt,
      timestamp: Date.now()
    })
  }

  await scrollToBottom()

  try {
    await aiStore.sendMessage(userInput)    
    await scrollToBottom()
  } catch (error) {
    console.error('发送消息失败:', error)
    // 如果是终止操作，不显示错误提示
    if (error === 'Request canceled' || (error instanceof Error && (error.name === 'AbortError' || error.message === 'Request canceled'))) {
      isMessageTerminated.value = true
      await scrollToBottom()
      return
    }
    // 其他错误才显示错误提示
    await message(error instanceof Error ? error.message : '发送消息失败，请重试', { title: '错误' })
  }
}

const handleKeyDown = (e: KeyboardEvent) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault()
    sendMessage()
  }
}

const formatTime = (timestamp: number) => {
  return new Date(timestamp).toLocaleTimeString()
}

// 添加新的编辑状态管理
const editingSessionId = ref<string | null>(null)
const editingTitle = ref('')

// 开始编辑会话标题
const startEditing = (session: { id: string; title: string }) => {
  editingSessionId.value = session.id
  editingTitle.value = session.title
}

// 保存编辑的标题
const saveTitle = (session: { id: string; title: string }) => {
  if (editingTitle.value.trim()) {
    aiStore.updateSessionTitle(session.id, editingTitle.value.trim())
  }
  editingSessionId.value = null
}

// 处理编辑时的按键事件
const handleTitleKeydown = (e: KeyboardEvent, session: { id: string; title: string }) => {
  if (e.key === 'Enter') {
    e.preventDefault()
    saveTitle(session)
  } else if (e.key === 'Escape') {
    editingSessionId.value = null
  }
}

const addNewModelConfig = () => {
  const newConfig = {
    name: '新配置',
    model: '',
    apiKey: '',
    baseUrl: 'https://api.openai.com/v1/chat/completions',
    temperature: 0.7,
    maxTokens: 2000,
    topP: 1,
    frequencyPenalty: 0,
    presencePenalty: 0,
    systemPrompt: '你是一个有用的AI助手。',
    enableStreaming: true,
    provider: 'custom' as const
  }
  
  // 添加新配置并获取配置ID
  aiStore.addModelConfig(newConfig)
  
  // 获取最新添加的配置
  const latestConfig = aiStore.modelConfigs[aiStore.modelConfigs.length - 1]
  
  // 自动选中新配置
  if (latestConfig) {
    aiStore.currentModelConfigId = latestConfig.id
  }
}

const deleteModelConfig = async (id: string) => {
  if (aiStore.modelConfigs.length <= 1) {
    await message('至少保留一个模型配置', { title: '提示' })
    return
  }
  
  try {
    await message('确定要删除此模型配置吗？', { 
      title: '确认'
    })
    aiStore.deleteModelConfig(id)
  } catch (error) {
    console.error('删除模型配置失败:', error)
  }
}

const copyMessage = async (content: string) => {
  try {
    await writeText(content)
  } catch (error) {
    console.error('复制失败:', error)
    await message('复制失败，请重试', { title: '错误' })
  }
}

// 添加复制状态管理
const copiedStates = ref<Map<number, boolean>>(new Map())

// 处理复制并显示状态
const handleCopy = async (msg: ChatMessage) => {
  try {
    await copyMessage(msg.content)
    // 创建新的 Map 来触发响应式更新
    const newStates = new Map(copiedStates.value)
    newStates.set(msg.timestamp, true)
    copiedStates.value = newStates
    // 1.5秒后清除状态
    setTimeout(() => {
      const updatedStates = new Map(copiedStates.value)
      updatedStates.delete(msg.timestamp)
      copiedStates.value = updatedStates
    }, 1500)
  } catch (error) {
    console.error('复制失败:', error)
  }
}

const validateCurrentConfig = async () => {
  const currentConfig = aiStore.getCurrentModelConfig()
  if (!currentConfig) return

  try {
    await aiStore.validateConfig(currentConfig)
    await message('配置验证成功', { title: '成功' })
  } catch (error) {
    await message('配置验证失败：' + (error instanceof Error ? error.message : '未知错误'), { title: '错误' })
  }
}

const isLastMessage = (msg: ChatMessage) => {
  const currentSession = aiStore.getCurrentSession()
  if (!currentSession) return false
  
  const messages = currentSession.messages
  return msg === messages[messages.length - 1]
}

// 添加编辑相关的状态
const showEditDialog = ref(false)
const editingMessage = ref<ChatMessage | null>(null)

// 编辑消息
const editMessage = (message: ChatMessage) => {
  editingMessage.value = message
  showEditDialog.value = true
}

// 保存编辑后的消息
const saveEditedMessage = (content: string) => {
  if (!editingMessage.value) return
  
  const session = aiStore.getCurrentSession()
  if (!session) return

  const messageIndex = session.messages.findIndex(m => m === editingMessage.value)
  if (messageIndex === -1) return

  // 更新消息内容
  session.messages[messageIndex] = {
    ...session.messages[messageIndex],
    content
  }
}

// 渲染 markdown
const renderMarkdown = (content: string) => {
  try {
    return marked(content)
  } catch (error) {
    console.error('Markdown 渲染失败:', error)
    return content
  }
}

// 添加自动聚焦指令
const vFocus = {
  mounted: (el: HTMLElement) => el.focus()
}

// 添加模型列表相关的状态
const isLoadingModels = ref(false)
const availableModels = ref<string[]>([])

// 刷新模型列表
const refreshModelList = async () => {
  const currentConfig = aiStore.getCurrentModelConfig()
  if (!currentConfig || !currentConfig.apiKey) {
    await message('请先配置 API 密钥', { title: '提示' })
    return
  }

  isLoadingModels.value = true
  try {
    availableModels.value = await aiStore.getModelList(currentConfig.id)
  } catch (error) {
    console.error('获取模型列表失败:', error)
    await message(error instanceof Error ? error.message : '获取模型列表失败', { title: '错误' })
    availableModels.value = []
  } finally {
    isLoadingModels.value = false
  }
}

// 监听配置 ID 变化，自动尝试获取模型列表
watch(
  () => aiStore.currentModelConfigId,
  () => {
    const currentConfig = aiStore.getCurrentModelConfig()
    if (currentConfig && currentConfig.apiKey) {
      refreshModelList()
    }
  }
)

// 添加点击外部关闭下拉框的处理
const handleClickOutside = (event: MouseEvent) => {
  const target = event.target as HTMLElement
  if (!target.closest('.model-dropdown')) {
    showModelDropdown.value = false
  }
}
</script>

<template>
  <div class="h-full flex relative overflow-hidden">
    <!-- 左侧会话列表 -->
    <div
      class="h-full sidebar flex flex-col border-r border-base-200/50 transition-all duration-300 ease-out relative bg-base-200/95"
      :style="{ width: `${sidebarWidth}px` }"
    >
      <!-- 侧边栏内容 -->
      <div class="flex flex-col h-full relative">
        <!-- 顶部区域 -->
        <div class="h-14 flex items-center px-4 bg-base-300/30 border-b border-base-200/50">
          <div class="flex items-center gap-3 flex-1 min-w-0">
            <span 
              class="font-medium text-base whitespace-nowrap transition-all duration-300"
              :class="{ 'opacity-0': isSidebarCollapsed }"
            >会话列表</span>
          </div>
          <!-- 折叠按钮 -->
          <button
            class="btn btn-ghost btn-sm btn-circle ml-2 hover:bg-base-100/50"
            @click="isSidebarCollapsed = !isSidebarCollapsed"
            :title="isSidebarCollapsed ? '展开侧边栏' : '收起侧边栏'"
          >
            <i 
              class="ri-arrow-left-s-line transition-transform duration-300"
              :class="{ 'rotate-180': isSidebarCollapsed }"
            ></i>
          </button>
        </div>

        <!-- 新对话按钮 -->
        <div class="p-3">
          <button
            class="w-full flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm transition-all duration-200 group bg-base-100 hover:bg-primary/10 border border-base-200/50 hover:border-primary/30"
            :class="[isSidebarCollapsed ? 'justify-center aspect-square !p-0' : 'justify-start']"
            @click="aiStore.createSession()"
          >
            <i 
              class="ri-add-line text-base transition-all duration-200 group-hover:text-primary group-hover:rotate-90"
              :class="{ 'text-lg': isSidebarCollapsed }"
            ></i>
            <span 
              class="transition-all duration-200 group-hover:text-primary"
              :class="{ 'hidden': isSidebarCollapsed }"
            >新对话</span>
          </button>
        </div>
        
        <!-- 会话列表 -->
        <div 
          class="flex-1 overflow-y-auto px-3 space-y-1"
          :class="{ 'pb-20': isSidebarCollapsed }"
        >
          <div
            v-for="session in [...aiStore.sessions].sort((a, b) => b.updatedAt - a.updatedAt)"
            :key="session.id"
            class="group rounded-lg cursor-pointer transition-all duration-200"
            :class="[
              session.id === aiStore.currentSessionId ? 
                'bg-base-100 shadow-sm ring-1 ring-primary/20' : 
                'hover:bg-base-100'
            ]"
            @click="aiStore.currentSessionId = session.id"
          >
            <div class="flex items-center gap-3 p-2.5 relative">
              <!-- 会话图标和标题 -->
              <div class="flex items-center gap-3 flex-1 min-w-0"
                :class="[isSidebarCollapsed ? 'justify-center' : '']"
              >
                <div class="relative flex items-center justify-center w-7 h-7 rounded-md"
                  :class="[
                    session.id === aiStore.currentSessionId ? 
                      'bg-primary/10' : 'bg-base-200/50'
                  ]"
                >
                  <i 
                    class="ri-message-3-line text-base flex-shrink-0 transition-colors"
                    :class="[
                      { 'text-lg': isSidebarCollapsed },
                      { 'text-primary': session.id === aiStore.currentSessionId }
                    ]"
                  ></i>
                </div>
                <!-- 编辑状态 -->
                <template v-if="editingSessionId === session.id && !isSidebarCollapsed">
                  <input
                    type="text"
                    v-model="editingTitle"
                    class="input input-xs input-ghost w-full focus:bg-base-100/50 focus:ring-1 focus:ring-primary/30"
                    @keydown="handleTitleKeydown($event, session)"
                    @blur="saveTitle(session)"
                    ref="titleInput"
                    v-focus
                  >
                </template>
                <!-- 显示状态 -->
                <span
                  v-else-if="!isSidebarCollapsed"
                  class="truncate transition-all duration-200 text-sm"
                  :class="[
                    { 'text-primary font-medium': session.id === aiStore.currentSessionId }
                  ]"
                  @click="aiStore.currentSessionId = session.id"
                  @dblclick="startEditing(session)"
                >{{ session.title }}</span>
              </div>
              
              <!-- 操作按钮 -->
              <div 
                v-if="!isSidebarCollapsed"
                class="flex gap-1 transition-opacity duration-200"
                :class="session.id === aiStore.currentSessionId ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'"
              >
                <button
                  v-if="editingSessionId !== session.id"
                  class="p-1.5 rounded-md hover:bg-base-200/80 text-base-content/70 hover:text-primary"
                  @click.stop="startEditing(session)"
                >
                  <i class="ri-edit-line text-sm"></i>
                </button>
                <button
                  class="p-1.5 rounded-md hover:bg-base-200/80 text-base-content/70 hover:text-error"
                  @click.stop="aiStore.deleteSession(session.id)"
                >
                  <i class="ri-delete-bin-line text-sm"></i>
                </button>
              </div>
            </div>
          </div>
        </div>

        <!-- 底部控制区 -->
        <div 
          class="border-t border-base-200/50 bg-base-300/30 transition-all duration-300"
          :class="[
            isSidebarCollapsed ? 'absolute bottom-0 left-0 right-0 pt-10 bg-gradient-to-t from-base-200 to-transparent' : ''
          ]"
        >
          <div 
            class="p-3 flex items-center gap-2"
            :class="[isSidebarCollapsed ? 'flex-col' : '']"
          >
            <button
              class="flex items-center gap-2 px-3 py-2 rounded-lg text-sm transition-all duration-200 hover:bg-base-100 flex-1 justify-center"
              :class="[{ 'w-10 h-10 !p-0': isSidebarCollapsed }]"
              @click="showSettings = true"
            >
              <i 
                class="ri-settings-3-line"
                :class="{ 'text-lg': isSidebarCollapsed }"
              ></i>
              <span 
                :class="{ 'hidden': isSidebarCollapsed }"
              >设置</span>
            </button>
          </div>
        </div>
      </div>
    </div>

    <!-- 右侧聊天区域 -->
    <div class="flex-1 flex flex-col bg-gradient-to-b from-base-100 to-base-100/95 relative">
      <!-- 聊天记录 -->
      <div 
        ref="chatContainer"
        class="flex-1 p-4 md:p-6 overflow-y-auto space-y-4 scroll-smooth"
      >
        <template v-if="aiStore.getCurrentSession()?.messages.length">
          <div 
            v-for="msg in aiStore.getCurrentSession()?.messages.filter(m => m.role !== 'system')"
            :key="msg.timestamp"
            class="flex group animate-fade-in"
            :class="msg.role === 'user' ? 'justify-end' : 'justify-start'"
          >
            <div
              class="w-[85%] md:w-[75%] lg:w-[65%] rounded-xl p-3 md:p-4 relative transition-all duration-200 hover:shadow-lg"
              :class="[
                msg.role === 'user' ? 
                  'bg-gradient-to-br from-success/90 to-success/80 text-success-content shadow-success/20 ml-auto' : 
                  'bg-gradient-to-br from-base-200 to-base-200/90 shadow-base-300/20 mr-auto backdrop-blur-sm'
              ]"
            >
              <div class="flex items-center gap-2 text-xs md:text-sm mb-2 md:mb-3">
                <span class="font-medium flex items-center gap-1.5">
                  <i :class="msg.role === 'user' ? 'ri-user-smile-line' : 'ri-robot-line'"></i>
                  {{ msg.role === 'user' ? '你' : 'AI' }}
                </span>
                <span class="opacity-50 text-xs">{{ formatTime(msg.timestamp) }}</span>
                <span 
                  v-if="msg.role === 'assistant'" 
                  class="opacity-70 text-xs flex items-center gap-1 bg-base-300/30 px-2 py-0.5 rounded-full ml-2"
                >
                  <i class="ri-cpu-line"></i>
                  {{ msg.model || '未知模型' }}
                </span>
                <div class="flex-1"></div>
                <div class="flex gap-1">
                  <button
                    class="btn btn-xs btn-ghost gap-1 px-3 backdrop-blur-sm tooltip tooltip-bottom"
                    :data-tip="copiedStates.get(msg.timestamp) ? '已复制！' : '复制消息'"
                    @click.stop="handleCopy(msg)"
                  >
                    <i :class="copiedStates.get(msg.timestamp) ? 'ri-check-line text-success' : 'ri-file-copy-line'"></i>
                    {{ copiedStates.get(msg.timestamp) ? '已复制' : '复制' }}
                  </button>
                  <button
                    class="btn btn-xs btn-ghost gap-1 px-3 backdrop-blur-sm tooltip tooltip-bottom"
                    data-tip="编辑消息"
                    @click.stop="editMessage(msg)"
                  >
                    <i class="ri-edit-line"></i>
                    编辑
                  </button>
                </div>
              </div>
              <div 
                class="prose prose-sm md:prose-base max-w-full dark:prose-invert prose-pre:bg-base-300/30 prose-pre:text-sm"
                :class="{ 
                  'animate-pulse': msg.role === 'assistant' && 
                    aiStore.isStreaming && 
                    isLastMessage(msg) && 
                    !msg.content.trim(),
                  'streaming': msg.role === 'assistant' && 
                    aiStore.isStreaming && 
                    isLastMessage(msg) && 
                    msg.content.trim()
                }"
              >
                <template v-if="msg.content">
                  <div v-if="shouldCollapseMessage(msg.content)" class="message-content relative">
                    <div 
                      v-html="renderMarkdown(getMessageContent(msg))"
                      :class="{ 'opacity-60': isMessageCollapsed(msg.timestamp) }"
                    ></div>
                    <div 
                      class="flex justify-center mt-2 gap-2"
                    >
                      <button
                        class="btn btn-xs btn-ghost gap-1 px-3 backdrop-blur-sm"
                        @click.stop="toggleMessageCollapse(msg.timestamp)"
                      >
                        <i :class="isMessageCollapsed(msg.timestamp) ? 'ri-arrow-down-s-line' : 'ri-arrow-up-s-line'"></i>
                        {{ isMessageCollapsed(msg.timestamp) ? '展开全部' : '收起内容' }}
                      </button>
                      <button
                        class="btn btn-xs btn-ghost gap-1 px-3 backdrop-blur-sm tooltip tooltip-bottom"
                        :data-tip="copiedStates.get(msg.timestamp) ? '已复制！' : '复制消息'"
                        @click.stop="handleCopy(msg)"
                      >
                        <i :class="copiedStates.get(msg.timestamp) ? 'ri-check-line text-success' : 'ri-file-copy-line'"></i>
                        {{ copiedStates.get(msg.timestamp) ? '已复制' : '复制' }}
                      </button>
                      <button
                        class="btn btn-xs btn-ghost gap-1 px-3 backdrop-blur-sm tooltip tooltip-bottom"
                        data-tip="编辑消息"
                        @click.stop="editMessage(msg)"
                      >
                        <i class="ri-edit-line"></i>
                        编辑
                      </button>
                    </div>
                    <div 
                      v-if="isMessageCollapsed(msg.timestamp)"
                      class="absolute bottom-0 left-0 right-0 h-12 bg-gradient-to-t pointer-events-none"
                      :class="msg.role === 'user' ? 'from-primary/10' : 'from-base-200/50'"
                    ></div>
                  </div>
                  <div v-else class="message-content" v-html="renderMarkdown(msg.content)"></div>
                </template>
                <template v-else-if="msg.role === 'assistant' && isLastMessage(msg)">
                  <div class="flex items-center gap-2">
                    <span v-if="isMessageTerminated" class="text-error flex items-center gap-1">
                      <i class="ri-stop-circle-line"></i>
                      已终止
                    </span>
                    <span v-else class="animate-pulse">思考中...</span>
                  </div>
                </template>
              </div>
            </div>
          </div>
        </template>
        <div 
          v-else
          class="flex flex-col items-center justify-center h-full text-base-content/50 space-y-4"
        >
          <i class="ri-chat-3-line text-4xl opacity-30"></i>
          <span>开始新的对话...</span>
        </div>
      </div>

      <!-- 输入区域 -->
      <div class="input-area p-3 md:p-4 border-t border-base-300/50">
        <div class="flex gap-2 max-w-4xl mx-auto relative">
          <textarea
            ref="textareaRef"
            v-model="messageInput"
            class="textarea textarea-bordered flex-1 shadow-sm focus:ring-1 focus:ring-primary/50 focus:border-primary/50 transition-all duration-200 min-h-[60px] bg-base-100/50"
            :class="{ 'opacity-50': aiStore.isProcessing }"
            placeholder="输入消息，按Enter发送，Shift+Enter换行..."
            rows="1"
            @keydown="handleKeyDown"
            :disabled="aiStore.isProcessing"
          ></textarea>
          <button
            v-if="!aiStore.isProcessing"
            class="btn btn-primary self-end shadow-sm hover:shadow-md transition-all duration-200 btn-send"
            :class="{ 
              'opacity-50': !messageInput.trim()
            }"
            :disabled="!messageInput.trim()"
            @click="sendMessage"
          >
            <i class="ri-send-plane-fill"></i>
          </button>
          <button
            v-else
            class="btn btn-error self-end shadow-sm hover:shadow-md transition-all duration-200"
            @click="aiStore.stopGenerating"
          >
            <i class="ri-stop-circle-line"></i>
            停止生成
          </button>
        </div>
      </div>
    </div>

    <!-- 设置抽屉 -->
    <div
      class="fixed inset-0 bg-black/30 backdrop-blur-sm transition-all duration-300 z-50"
      :class="{ 'opacity-100': showSettings, 'opacity-0 pointer-events-none': !showSettings }"
      @click="showSettings = false"
    >
      <div
        class="settings-panel absolute right-0 top-0 h-full w-[420px] shadow-2xl transition-transform duration-300 ease-out border-l border-base-200/50 flex flex-col bg-base-100/95"
        :class="{ 'translate-x-0': showSettings, 'translate-x-full': !showSettings }"
        @click.stop
      >
        <!-- 头部 -->
        <div class="px-5 h-14 border-b border-base-200 flex justify-between items-center bg-base-200/90 backdrop-blur supports-[backdrop-filter]:bg-base-200/80">
          <h3 class="font-medium text-base flex items-center gap-2">
            <i class="ri-settings-3-line opacity-70"></i>
            AI模型设置
          </h3>
          <button 
            class="btn btn-sm btn-circle btn-ghost hover:bg-base-200/80"
            @click="showSettings = false"
          >
            <i class="ri-close-line"></i>
          </button>
        </div>

        <!-- 内容区域 -->
        <div class="flex-1 overflow-y-auto p-5 space-y-5 bg-base-100/95">
          <!-- 模型选择和管理 -->
          <div class="flex items-center gap-2">
            <div class="flex-1">
              <select 
                class="select select-bordered select-xs w-full focus:outline-none focus:ring-1 focus:ring-primary/50" 
                v-model="aiStore.currentModelConfigId"
              >
                <option 
                  v-for="config in aiStore.modelConfigs" 
                  :key="config.id" 
                  :value="config.id"
                >
                  {{ config.name }}
                </option>
              </select>
            </div>
            <div class="flex gap-1.5">
              <button 
                class="btn btn-xs btn-square btn-ghost hover:bg-success/10 tooltip tooltip-left"
                data-tip="验证配置"
                @click="validateCurrentConfig"
              >
                <i class="ri-check-line text-success"></i>
              </button>
              <button 
                class="btn btn-xs btn-square btn-ghost hover:bg-error/10 tooltip tooltip-left"
                data-tip="删除配置"
                @click="deleteModelConfig(aiStore.getCurrentModelConfig()?.id || '')"
                v-if="aiStore.modelConfigs.length > 1"
              >
                <i class="ri-delete-bin-line text-error"></i>
              </button>
              <button 
                class="btn btn-xs btn-square btn-ghost hover:bg-primary/10 tooltip tooltip-left"
                data-tip="新增配置"
                @click="addNewModelConfig()"
              >
                <i class="ri-add-line text-primary"></i>
              </button>
            </div>
          </div>

          <!-- 当前模型配置 -->
          <div v-if="aiStore.getCurrentModelConfig()" class="card bg-base-200/90 backdrop-blur-sm">
            <div class="card-body p-4 space-y-4">
              <h3 class="text-xs font-medium flex items-center gap-1.5 text-base-content/70">
                <i class="ri-settings-4-line"></i>
                配置参数
              </h3>
              <!-- 基础配置 -->
              <div class="grid grid-cols-2 gap-3">
                <div class="form-control">
                  <label class="label py-0.5">
                    <span class="label-text text-xs opacity-70">名称</span>
                  </label>
                  <input 
                    type="text" 
                    class="input input-bordered input-xs w-full bg-base-100/50 focus:outline-none focus:ring-1 focus:ring-primary/50" 
                    v-model="aiStore.getCurrentModelConfig()!.name"
                    placeholder="模型配置名称"
                  >
                </div>
                <div class="form-control">
                  <label class="label py-0.5">
                    <span class="label-text text-xs opacity-70">最大Token数</span>
                  </label>
                  <input 
                    type="number" 
                    class="input input-bordered input-xs w-full bg-base-100/50 focus:outline-none focus:ring-1 focus:ring-primary/50" 
                    v-model="aiStore.getCurrentModelConfig()!.maxTokens"
                    min="1"
                    max="4000"
                  >
                </div>
              </div>

              <div class="form-control">
                <label class="label py-0.5">
                  <span class="label-text text-xs opacity-70">模型</span>
                  <button 
                    class="btn btn-xs btn-ghost gap-1"
                    @click="refreshModelList"
                    :class="{ 'loading': isLoadingModels }"
                  >
                    <i class="ri-refresh-line" v-if="!isLoadingModels"></i>
                    获取可用模型
                  </button>
                </label>
                <div class="relative model-dropdown">
                  <input 
                    type="text" 
                    class="input input-bordered input-xs w-full bg-base-100/50 focus:outline-none focus:ring-1 focus:ring-primary/50" 
                    v-model="aiStore.getCurrentModelConfig()!.model"
                    placeholder="选择或输入模型标识符"
                    @focus="showModelDropdown = true"
                  >
                  <div 
                    v-if="showModelDropdown && availableModels.length > 0"
                    class="absolute top-full left-0 right-0 mt-1 bg-base-100 rounded-lg shadow-lg border border-base-200/50 max-h-48 overflow-y-auto z-10"
                  >
                    <div 
                      v-for="model in availableModels" 
                      :key="model"
                      class="px-3 py-1.5 hover:bg-base-200/50 cursor-pointer text-sm truncate"
                      @click="() => {
                        aiStore.getCurrentModelConfig()!.model = model;
                        showModelDropdown = false;
                      }"
                    >
                      {{ model }}
                    </div>
                  </div>
                </div>
              </div>

              <div class="form-control">
                <label class="label py-0.5">
                  <span class="label-text text-xs opacity-70">API Base URL</span>
                </label>
                <input 
                  type="text" 
                  class="input input-bordered input-xs w-full bg-base-100/50 focus:outline-none focus:ring-1 focus:ring-primary/50" 
                  v-model="aiStore.getCurrentModelConfig()!.baseUrl"
                  placeholder="API Base URL"
                >
              </div>

              <div class="form-control">
                <label class="label py-0.5">
                  <span class="label-text text-xs opacity-70">API密钥</span>
                </label>
                <div class="relative">
                  <input 
                    :type="showApiKey ? 'text' : 'password'" 
                    class="input input-bordered input-xs w-full bg-base-100/50 focus:outline-none focus:ring-1 focus:ring-primary/50 pr-8" 
                    v-model="aiStore.getCurrentModelConfig()!.apiKey"
                    placeholder="请输入API密钥"
                  >
                  <button 
                    class="absolute right-2 top-1/2 -translate-y-1/2 w-6 h-6 flex items-center justify-center rounded-full hover:bg-base-200/50 transition-colors"
                    @click="showApiKey = !showApiKey"
                    type="button"
                  >
                    <i :class="showApiKey ? 'ri-eye-off-line' : 'ri-eye-line'" class="text-base-content/70 text-sm"></i>
                  </button>
                </div>
              </div>

              <div class="form-control">
                <label class="label py-0.5">
                  <span class="label-text text-xs opacity-70">温度 ({{ aiStore.getCurrentModelConfig()!.temperature }})</span>
                </label>
                <input 
                  type="range" 
                  class="range range-primary range-xs" 
                  v-model.number="aiStore.getCurrentModelConfig()!.temperature"
                  min="0" 
                  max="2" 
                  step="0.1"
                >
              </div>

              <div class="form-control">
                <label class="label py-0.5">
                  <span class="label-text text-xs opacity-70">System Prompt</span>
                  <span class="label-text-alt text-xs opacity-50">定义AI助手的角色和行为</span>
                </label>
                <textarea 
                  class="textarea textarea-bordered textarea-xs w-full bg-base-100/50 focus:outline-none focus:ring-1 focus:ring-primary/50 min-h-[80px] text-sm"
                  v-model="aiStore.getCurrentModelConfig()!.systemPrompt"
                  placeholder="输入 System Prompt 来定义AI助手的角色和行为特征..."
                ></textarea>
              </div>

              <!-- 流式对话开关 -->
              <!-- <div class="form-control">
                <label class="label cursor-pointer justify-start gap-2">
                  <input 
                    type="checkbox" 
                    class="toggle toggle-primary toggle-sm"
                    v-model="aiStore.getCurrentModelConfig()!.enableStreaming"
                  >
                  <span class="label-text text-xs opacity-70">启用流式对话</span>
                  <span class="label-text-alt text-xs opacity-50">实时显示AI回复内容</span>
                </label>
              </div> -->
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>

  <!-- 编辑消息对话框 -->
  <MessageEditDialog
    v-model="showEditDialog"
    :message="editingMessage"
    @save="saveEditedMessage"
  />
</template>

<style scoped>
/* 基础变量定义 */
:root {
  --transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
  --animation-timing: cubic-bezier(0.4, 0, 0.2, 1);
  --blur-amount: 12px;
  --gradient-opacity-from: 0.95;
  --gradient-opacity-to: 0.9;
}

/* 统一背景渐变 */
.sidebar {
  @apply bg-gradient-to-br from-base-200/[var(--gradient-opacity-from)] to-base-200/[var(--gradient-opacity-to)];
  backdrop-filter: blur(var(--blur-amount));
  -webkit-backdrop-filter: blur(var(--blur-amount));
}

.settings-panel {
  @apply bg-gradient-to-br from-base-100/[var(--gradient-opacity-from)] to-base-100/[var(--gradient-opacity-to)];
  backdrop-filter: blur(var(--blur-amount));
  -webkit-backdrop-filter: blur(var(--blur-amount));
}

.input-area {
  @apply bg-gradient-to-t from-base-100/[var(--gradient-opacity-from)] to-base-100/[var(--gradient-opacity-to)];
  backdrop-filter: blur(var(--blur-amount));
  -webkit-backdrop-filter: blur(var(--blur-amount));
}

/* 统一消息气泡样式 */
.message-bubble {
  @apply rounded-xl p-3 md:p-4 relative transition-all duration-200;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
}

.message-bubble:hover {
  box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.05), 0 4px 6px -2px rgba(0, 0, 0, 0.03);
  transform: translateY(-1px);
}

/* 统一按钮样式 */
.btn {
  @apply transition-all duration-200 ease-out;
  transform-origin: center;
}

.btn:not(:disabled):hover {
  @apply shadow-md;
  transform: scale(1.02);
  filter: brightness(1.02);
}

.btn:active {
  transform: scale(0.98);
}

/* 统一输入框样式 */
.input,
.textarea,
.select {
  @apply transition-all duration-200 bg-base-100/50;
  box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.02);
}

.input:focus,
.textarea:focus,
.select:focus {
  @apply ring-2 ring-primary/20 border-primary/30;
  box-shadow: 0 0 0 2px rgba(var(--p), 0.1);
}

/* 统一滚动条样式 */
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-track {
  @apply bg-transparent;
}

::-webkit-scrollbar-thumb {
  @apply bg-base-300/50 rounded-full transition-colors;
}

::-webkit-scrollbar-thumb:hover {
  @apply bg-base-content/20;
}

/* 统一卡片样式 */
.card {
  @apply transition-all duration-200;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.02), 0 1px 2px 0 rgba(0, 0, 0, 0.03);
}

.card:hover {
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.03), 0 2px 4px -1px rgba(0, 0, 0, 0.02);
  transform: translateY(-1px);
}

/* 统一动画效果 */
.animate-fade-in {
  animation: fadeIn 0.3s var(--animation-timing);
  animation-fill-mode: both;
  will-change: transform, opacity;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(8px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

/* 统一 Markdown 样式 */
:deep(.prose) {
  @apply max-w-none break-words leading-relaxed;
}

:deep(.prose pre) {
  @apply my-3 rounded-lg bg-base-300/20 border border-base-300/10;
  box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}

:deep(.prose code) {
  @apply px-1.5 py-0.5 rounded bg-base-300/20 text-sm border border-base-300/10;
  box-shadow: inset 0 1px 2px 0 rgba(0, 0, 0, 0.02);
}

:deep(.prose pre code) {
  @apply p-3 block border-none shadow-none bg-transparent;
}

:deep(.prose a) {
  @apply text-primary hover:text-primary/80 transition-colors underline decoration-primary/30 hover:decoration-primary;
}

:deep(.prose blockquote) {
  @apply border-l-4 border-base-300/50 pl-4 italic bg-base-300/10 py-2 rounded-r-lg;
}

:deep(.prose img) {
  @apply rounded-lg max-h-64 mx-auto shadow-sm;
  transition: transform 0.2s var(--transition-timing);
}

:deep(.prose img:hover) {
  transform: scale(1.02);
}

/* 统一列表样式 */
:deep(.prose ul),
:deep(.prose ol) {
  @apply my-2 space-y-1;
}

:deep(.prose li) {
  @apply transition-colors duration-200;
}

:deep(.prose li:hover) {
  @apply bg-base-300/10 rounded-lg;
}

/* 统一表格样式 */
:deep(.prose table) {
  @apply w-full border-collapse my-4 bg-base-100/50 rounded-lg overflow-hidden;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.02);
}

:deep(.prose th) {
  @apply bg-base-200/50 font-medium px-4 py-2 text-left;
}

:deep(.prose td) {
  @apply px-4 py-2 border-t border-base-300/20;
}

:deep(.prose tr) {
  @apply transition-colors duration-200;
}

:deep(.prose tr:hover) {
  @apply bg-base-200/30;
}

/* 优化移动端体验 */
@media (max-width: 768px) {
  .btn {
    @apply touch-manipulation;
  }
  
  .textarea {
    font-size: 16px;
  }
  
  .input-area {
    @apply pb-4;
  }
}

/* 优化暗色模式 */
:deep(.dark) {
  --gradient-opacity-from: 0.9;
  --gradient-opacity-to: 0.85;
}

:deep(.dark .prose) {
  @apply prose-invert;
}

:deep(.dark .prose pre),
:deep(.dark .prose code) {
  @apply bg-base-300/30 border-base-300/20;
}

:deep(.dark .prose blockquote) {
  @apply border-base-content/20 bg-base-300/20;
}

:deep(.dark .prose a) {
  @apply text-primary-content/90 hover:text-primary-content;
}

:deep(.dark) .card,
:deep(.dark) .input,
:deep(.dark) .textarea,
:deep(.dark) .select {
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
}

/* 添加一些必要的基础样式 */
.modal-backdrop {
  @apply bg-black/20 backdrop-blur-sm;
}

textarea {
  @apply resize-none;
}

/* 优化打字机效果 */
.streaming {
  animation: typing 0.15s ease-out;
  opacity: 1;
  transition: opacity 0.15s ease-out;
  position: relative;
}

.streaming::after {
  content: '';
  position: absolute;
  right: -2px;
  top: 50%;
  transform: translateY(-50%);
  width: 2px;
  height: 16px;
  background-color: currentColor;
  animation: blink 0.8s steps(2) infinite;
}

@keyframes blink {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

@keyframes typing {
  from {
    opacity: 0.5;
    transform: translateY(2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 添加输入框样式 */
.input-xs {
  @apply h-6 px-2 text-sm;
  min-height: 1.5rem;
}

.input-xs:focus {
  @apply outline-none;
}
</style> 